2012-09-04 22:16:00
在[上一篇](/2012/09/03/learning_atl_com_interface/)中,我们实现了COM_INTERFACE宏,并且重新写了一个含有WebBrowser的窗口。在那里我们留了中间层OleContainer。为了验证OleContainer的可用性,现在来写一个含有Windows Media Player(下文简称“WMP”)控件的窗口。
WMP控件的容器类除了IOleClientSite、IOleInPlaceSite、IOleInPlaceFrame外,还要实现IDispatch,这些接口的 IXXXImpl 都已经有了,所以做起来就比较方便了:
(http://xllib.codeplex.com/SourceControl/changeset/view/19631#315488)
1#include <wmp.h>
2#include <xl/Win32/COM/Objects/xlOleContainer.h>
3#include <xl/Win32/COM/InterfaceHelper/xlIDispatchImpl.h>
4
5namespace xl
6{
7 class MediaPlayerImpl : public OleContainerImpl,
8 public IDispatchImpl<>
9 {
10 public:
11 MediaPlayerImpl() : m_pWMPPlayer(nullptr)
12 {
13
14 }
15
16 ~MediaPlayerImpl()
17 {
18 DestroyMediaPlayer();
19 }
20
21 public:
22 bool CreateMediaPlayer(HWND hWnd, LPCRECT lpRect = nullptr)
23 {
24 DestroyMediaPlayer();
25
26 if (!CreateOleObject(__uuidof(WindowsMediaPlayer)))
27 {
28 return false;
29 }
30
31 if (!InPlaceActive(hWnd, lpRect))
32 {
33 return false;
34 }
35
36 HRESULT hr = m_pOleObj->QueryInterface(__uuidof(IWMPPlayer), (LPVOID *)&m_pWMPPlayer);
37
38 if (FAILED(hr))
39 {
40 return false;
41 }
42
43 return true;
44 }
45
46 void DestroyMediaPlayer()
47 {
48 if (m_pWMPPlayer != NULL)
49 {
50 m_pWMPPlayer->Release();
51 m_pWMPPlayer = nullptr;
52 }
53
54 DestroyOleObject();
55 }
56
57 protected:
58 IWMPPlayer *m_pWMPPlayer;
59 };
60
61 class MediaPlayer : public ComClass<MediaPlayer>,
62 public MediaPlayerImpl
63 {
64 public:
65 MediaPlayer()
66 {
67
68 }
69
70 ~MediaPlayer()
71 {
72 DestroyMediaPlayer();
73 }
74
75 public:
76 XL_COM_INTERFACE_BEGIN(MediaPlayer)
77 XL_COM_INTERFACE(IOleClientSite)
78 XL_COM_INTERFACE(IOleInPlaceSite)
79 XL_COM_INTERFACE(IOleInPlaceFrame)
80 XL_COM_INTERFACE(IDispatch)
81 XL_COM_INTERFACE_END()
82 };
83
84} // namespace xl
WindowsMediaPlayer这个coclass在wmp.h中定义,OleCreate的时候指定它就可以了。创建好了以后,拿到IWMPPlayer接口,就算完事了,后续的控制可以由该接口完成。
然后,仿照前面的样子写个例程:
#include <xl/Win32/COM/Objects/xlMediaPlayer.h>
class MediaPlayer : public xl::MediaPlayer
{
public:
void Play(LPCTSTR lpUrl)
{
BSTR bstrUrl = SysAllocString(lpUrl);
m_pWMPPlayer->put_URL(bstrUrl);
SysFreeString(bstrUrl);
}
};
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
const LPCTSTR CLASS_NAME = _T("MediaPlayerContainer");
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszClassName = CLASS_NAME;
RegisterClassEx(&wcex);
HWND hWnd = CreateWindow(CLASS_NAME,
_T("MediaPlayer Sample"),
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
nullptr,
nullptr,
hInstance,
nullptr);
if (hWnd == nullptr)
{
return 0;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
RECT rect = {};
GetClientRect(hWnd, &rect);
rect.left += 100;
rect.top += 100;
rect.right -= 100;
rect.bottom -= 100;
MediaPlayer mp;
if (!mp.CreateMediaPlayer(hWnd, &rect))
{
return 0;
}
mp.Play(_T("Sample.mid"));
MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, nullptr, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
上面测试了一下创建的时候指定一个矩形区域,看看是否能定位到目标位置。IWMPPlayer的URL属性表示要播放的文件路径或网络地址,设上的时候就会开始播放。运行效果:

以上见MediaPlayerSample.rar(http://pan.baidu.com/s/1txy2)
也可以和GUI类一起使用:
1#include <xl/Win32/GUI/xlWindow.h>
2#include <xl/Win32/COM/Objects/xlMediaPlayer.h>
3
4class MediaPlayer : public xl::MediaPlayer
5{
6public:
7 void Play(LPCTSTR lpUrl)
8 {
9 BSTR bstrUrl = SysAllocString(lpUrl);
10 m_pWMPPlayer->put_URL(bstrUrl);
11 SysFreeString(bstrUrl);
12 }
13};
14
15class MyWindow : public xl::Window
16{
17public:
18 MyWindow()
19 {
20 AppendMsgHandler(WM_DESTROY, MsgHandler(this, &MyWindow::OnDestroy));
21 }
22
23 ~MyWindow()
24 {
25
26 }
27
28private:
29 LRESULT OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
30 {
31 PostQuitMessage(0);
32 return 0;
33 }
34};
35
36int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
37 _In_opt_ HINSTANCE hPrevInstance,
38 _In_ LPTSTR lpCmdLine,
39 _In_ int nCmdShow)
40{
41 MyWindow wnd;
42
43 if (!wnd.Create())
44 {
45 return 0;
46 }
47
48 wnd.ShowWindow();
49
50 MediaPlayer mp;
51
52 if (!mp.CreateMediaPlayer(wnd.GetHWND()))
53 {
54 return 0;
55 }
56
57 mp.Play(_T("Sample.mid"));
58
59 MSG msg = {};
60
61 while (GetMessage(&msg, nullptr, 0, 0))
62 {
63 if (!TranslateAccelerator(msg.hwnd, nullptr, &msg))
64 {
65 TranslateMessage(&msg);
66 DispatchMessage(&msg);
67 }
68 }
69
70 return (int)msg.wParam;
71}
以上见MediaPlayerSample2.rar(http://pan.baidu.com/s/1gdd6YXH)
或者作为GUI类的成员:
1#include <xl/Win32/GUI/xlDialog.h>
2#include <xl/Win32/COM/Objects/xlMediaPlayer.h>
3
4class MediaPlayer : public xl::MediaPlayer
5{
6public:
7 void Play(LPCTSTR lpUrl)
8 {
9 BSTR bstrUrl = SysAllocString(lpUrl);
10 m_pWMPPlayer->put_URL(bstrUrl);
11 SysFreeString(bstrUrl);
12 }
13};
14
15class MyDialog : public xl::Dialog
16{
17private:
18 bool OnInitDialog()
19 {
20 if (!m_wmp.CreateMediaPlayer(m_hWnd))
21 {
22 return false;
23 }
24
25 m_wmp.Play(_T("Sample.mid"));
26
27 return true;
28 }
29
30private:
31 MediaPlayer m_wmp;
32};
33
34int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
35 _In_opt_ HINSTANCE hPrevInstance,
36 _In_ LPTSTR lpCmdLine,
37 _In_ int nCmdShow)
38{
39 MyDialog dlg;
40
41 if (!dlg.Create(400, 400))
42 {
43 return 0;
44 }
45
46 dlg.DoModal();
47
48 return 0;
49}
以上见MediaPlayerSample3.rar(http://pan.baidu.com/s/1gdmuySN)
也可以让GUI类继承于它(可能的话,可附加实现WMP的别的COM接口或给出别的对外操作方法):
1#include <xl/Win32/GUI/xlDialog.h>
2#include <xl/Win32/COM/Objects/xlMediaPlayer.h>
3
4class WMPDialog : public xl::Dialog,
5 public xl::MediaPlayer
6{
7private:
8 bool OnInitDialog()
9 {
10 if (!CreateMediaPlayer(m_hWnd))
11 {
12 return false;
13 }
14
15 return true;
16 }
17
18public:
19 void Play(LPCTSTR lpUrl)
20 {
21 BSTR bstrUrl = SysAllocString(lpUrl);
22 m_pWMPPlayer->put_URL(bstrUrl);
23 SysFreeString(bstrUrl);
24 }
25};
26
27int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
28 _In_opt_ HINSTANCE hPrevInstance,
29 _In_ LPTSTR lpCmdLine,
30 _In_ int nCmdShow)
31{
32 WMPDialog dlg;
33
34 if (!dlg.Create(400, 400))
35 {
36 return 0;
37 }
38
39 dlg.Play(_T("Sample.mid"));
40 dlg.DoModal();
41
42 return 0;
43}
以上见MediaPlayerSample4.rar(http://pan.baidu.com/s/1EoZFK)

示例的MIDI是我早年蛋疼的时候做的哦,希望大家喜欢。
首发:http://www.cppblog.com/Streamlet/archive/2012/09/04/189470.html